// SPDX-License-Identifier: GPL-2.0 or GPL-3.0
// Copyright © 2018-2019 Ariadne Devos
/* sHT -- process all events in a loop */

#if 0
/* XXX "worker.h" will be deleted */

#include "worker.h"

#include <sHT/bugs.h>
#include <sHT/compiler.h>

#include <errno.h>
#include <sys/epoll.h>

__attribute__((nonnull (1)))
__attribute__((warn_unused_result))
static int
sHT_wait_and_poll(struct sHT_worker *worker, int timeout)
{
	int n;
	int *err = &errno;
	do n = epoll_wait(worker->watches, worker->epoll_events, worker->todo->capacity, timeout);
	while (sHT_test_hidden(n, n < 0) && sHT_test_hidden(*err, *err == EINTR));
	sHT_require(n >= 0);
	return n;
}

__attribute__((nonnull (1, 2)))
static void
sHT_perform_task_wrapper(void *cookie, struct sHT_task *task)
{
	/* TODO: distinction between homogeneous and heterogeneous */
	sHT_perform_task(cookie, task);
}

__attribute__((nonnull (1)))
static void
sHT_worker_iteration(struct sHT_worker *worker)
{
	/* If there are things to do, do poll, such that other tasks may
	   make progress, but don't wait. */
	_Bool nonblock = sHT_test_hidden(worker->todo->n, worker->todo->n > 0);
	int n_events = sHT_wait_and_poll(worker, nonblock ? 0 : -1);
	sHT_schedule_events(worker, n_events);
	sHT_perform_all(worker, worker->todo, &sHT_perform_task_wrapper);
	/* XXX: notify the control thread (OOM ...) */
	sHT_todo(worker->flags);
}

_Noreturn void
sHT_worker(struct sHT_worker *worker)
{
	while (1)
		sHT_worker_iteration(worker);
}

#endif
